package com.meida.module.product.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.meida.common.constants.CommonConstants;
import com.meida.common.enums.VisiableEnum;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.entity.EntityMap;
import com.meida.common.mybatis.model.ListModel;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.model.SaveModel;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.FlymeUtils;
import com.meida.module.product.client.entity.ProdCategory;
import com.meida.module.product.client.entity.ProdProduct;
import com.meida.module.product.provider.mapper.ProdCategoryMapper;
import com.meida.module.product.provider.service.ProdCategoryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 店铺产品分类 实现类
 *
 * @author flyme
 * @date 2019-06-19
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ProdCategoryServiceImpl extends BaseServiceImpl<ProdCategoryMapper, ProdCategory> implements ProdCategoryService {


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody listEntityMap(ListModel model) {
        CriteriaQuery cq = new CriteriaQuery(model, ProdCategory.class);
        EntityMap params = cq.getRequestMap();
        Long categoryId = params.getLong("categoryId");
        String categoryName = params.get("categoryName");
        ApiAssert.isNotEmpty("请选择一级分类", categoryId);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryName", "categoryIcon");
        cq.eq("parentId", categoryId);
        cq.likeRight("categoryName", categoryName);
        cq.eq("categoryLevel", CommonConstants.LEVEL_2);
        cq.orderByAsc("sortOrder");
        return baseList(cq);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody listAll(ListModel listModel) {
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(listModel, ProdCategory.class);
        EntityMap params = cq.getRequestMap();
        String categoryName = params.get("categoryName");
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryName", "categoryIcon", "catagoryState", "sortOrder");
        cq.likeRight("categoryName", categoryName);
        cq.orderByAsc("sortOrder");
        return baseList(cq);
    }


    @Override
    public ResultBody add(SaveModel model) {
        CriteriaSave cs = new CriteriaSave(model, ProdCategory.class);
        ProdCategory category = cs.getEntity();
        Long companyId = OpenHelper.getCompanyId();
        String categoryName = category.getCategoryName();
        ApiAssert.isNotEmpty("分类名称不能为空", categoryName);
        ProdCategory prodCategory = getProdCategory(categoryName, companyId);
        ApiAssert.isEmpty("分类已存在", prodCategory);

        Long parentId = FlymeUtils.isEmpty(category.getParentId()) ? 0L : category.getParentId();
        ProdCategory parent = getById(parentId);

        Integer count;
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        if (parentId.equals(0L)) {
            count = count(cq.eq("parentId", cs.getParams("parentId")));
            cs.put("categoryLevel", 1);
        } else {
            count = count(cq.eq("parentId", parent.getCategoryId()));
            cs.put("categoryLevel", 2);
        }
        BigDecimal sortOrder = FlymeUtils.getBigDecimal(new BigDecimal(count), "0").add(new BigDecimal(1));
        cs.put("sortOrder", FlymeUtils.isEmpty(category.getSortOrder()) ? new BigDecimal("0") : category.getSortOrder());

        cs.put("parentId", parentId);
        cs.put("categoryName", "分类名称" + sortOrder);
        cs.put("sortOrder", sortOrder);
        cs.put("catagoryState", CommonConstants.ENABLED);
        cs.put("companyId", companyId);
        return baseAdd(cs);
    }


    @Override
    public ResultBody setState(Long categoryId, VisiableEnum visiableEnum) {
        ApiAssert.isNotEmpty("主键不能为空", categoryId);
        ApiAssert.isNotEmpty("状态不能为空", visiableEnum);
        UpdateWrapper up = new UpdateWrapper();
        up.set("catagoryState", visiableEnum.getCode());
        up.eq("categoryId", categoryId);
        boolean result = update(up);
        if (result) {
            return ResultBody.msg(visiableEnum.getName() + "成功");
        } else {
            return ResultBody.failed(visiableEnum.getName() + "失败");
        }
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<EntityMap> selectShopFirstCategory(Long shopId) {
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId1");
        cq.eq(ProdProduct.class, "shopId", shopId);
        cq.groupBy("categoryId");
        List<EntityMap> categoryList1 = selectEntityMap(cq);
        return categoryList1;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<EntityMap> selectShopSecondCategory(Long shopId,Long categoryId) {
        CriteriaQuery cq2 = new CriteriaQuery(ProdCategory.class);
        cq2.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq2.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId2");
        cq2.eq(ProdProduct.class, "shopId", shopId);
        cq2.eq(ProdCategory.class,"parentId",categoryId);
        cq2.groupBy("categoryId");
        List<EntityMap> categoryList2 = selectEntityMap(cq2);
        return categoryList2;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<EntityMap> selectFirstCategory(String categoryName) {
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "categoryName", "categoryIcon", "parentId");
        cq.eq("categoryLevel", CommonConstants.LEVEL_1);
        cq.likeRight("categoryName", categoryName);
        cq.orderByAsc("sortOrder");
        return selectEntityMap(cq);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<EntityMap> selectSecondCategory(Long categoryId, String categoryName) {
        ApiAssert.isNotEmpty("请选择一级分类", categoryId);
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryName", "categoryIcon");
        cq.eq("parentId", categoryId);
        cq.likeRight("categoryName", categoryName);
        cq.eq("categoryLevel", CommonConstants.LEVEL_2);
        cq.orderByAsc("sortOrder");
        return selectEntityMap(cq);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody selectAllCategory() {
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq.orderByAsc("sortOrder");
        List<EntityMap> allList = selectEntityMap(cq);
        List<EntityMap> result = buildTree(allList, 0L);
        return ResultBody.ok(result);
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody selectShopCategory(Long shopId) {
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId1");
        cq.eq(ProdProduct.class, "shopId", shopId);
        cq.groupBy("categoryId");
        List<EntityMap> categoryList1 = selectEntityMap(cq);

        CriteriaQuery cq2 = new CriteriaQuery(ProdCategory.class);
        cq2.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq2.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId2");
        cq2.eq(ProdProduct.class, "shopId", shopId);
        cq2.groupBy("categoryId");
        List<EntityMap> categoryList2 = selectEntityMap(cq2);


        CriteriaQuery cq3 = new CriteriaQuery(ProdCategory.class);
        cq3.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq3.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId3");
        cq3.eq(ProdProduct.class, "shopId", shopId);
        cq3.groupBy("categoryId");
        List<EntityMap> categoryList3 = selectEntityMap(cq3);

        List<EntityMap> allList = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(categoryList1)) {
            allList.addAll(categoryList1);
        }
        if (FlymeUtils.isNotEmpty(categoryList2)) {
            allList.addAll(categoryList2);
        }
        if (FlymeUtils.isNotEmpty(categoryList3)) {
            allList.addAll(categoryList3);
        }
        List<EntityMap> result = buildTree(allList, 0L);
        return ResultBody.ok(result);
    }

    @Override
    public List<String> selectNames(String[] categoryIds) {
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        cq.select("categoryName");
        cq.in(true, "categoryId", categoryIds);
        return listObjs(cq, e -> e.toString());
    }


    @Override
    public List<String> selectIds(String[] categoryNames) {
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        cq.select("categoryId");
        cq.in(true, "categoryName", categoryNames);
        return listObjs(cq, e -> e.toString());
    }


    /**
     * 递归构建
     *
     * @param list
     * @param parentId
     * @return
     */
    private static List<EntityMap> buildTree(List<EntityMap> list, Long parentId) {
        List<EntityMap> result = new ArrayList();
        list.forEach(category -> {
            Long categoryId = category.getLong("categoryId");
            Long pid = category.getLong("parentId");
            Integer categoryLevel = category.get("categoryLevel");
            if (parentId.equals(pid)) {
                List child = buildTree(list, categoryId);
                if (categoryLevel.equals(1)) {
                    category.put("child", child);
                }
                result.add(category);
            }
        });
        return result;
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ProdCategory getProdCategory(String categoryName, Long companyId) {
        CriteriaQuery<ProdCategory> cq = new CriteriaQuery(ProdCategory.class);
        cq.eq(true, "categoryName", categoryName);
        cq.eq(true, "companyId", companyId);
        return getOne(cq);
    }
}
